package com.framework.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.framework.core.common.constant.CacheConstants;
import com.framework.core.common.enums.StatusEnum;
import com.framework.core.exception.CustomException;
import com.framework.system.entity.SysConfig;
import com.framework.system.entity.dto.SysConfigAddDTO;
import com.framework.system.entity.dto.SysConfigEditDTO;
import com.framework.system.entity.dto.SysConfigQueryDTO;
import com.framework.system.entity.vo.SysConfigListVO;
import com.framework.system.entity.vo.SysConfigVO;
import com.framework.system.mapper.SysConfigMapper;
import com.framework.system.service.ISysConfigService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 系统配置 服务实现类
 * </p>
 *
 * @author Kevin
 * @since 2021-06-23
 */
@Service
@AllArgsConstructor
@Slf4j
public class SysConfigServiceImpl implements ISysConfigService {

    private SysConfigMapper sysConfigMapper;

    @Override
    public Page<SysConfigListVO> selectPage(Page reqPage, SysConfigQueryDTO req) {
        LambdaQueryWrapper<SysConfig> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigName()), SysConfig::getConfigName, req.getConfigName());
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigKey()), SysConfig::getConfigKey, req.getConfigKey());
        queryWrapper.orderByDesc(SysConfig::getCreateTime);
        Page<SysConfig> page = sysConfigMapper.selectPage(reqPage, queryWrapper);
        Page<SysConfigListVO> voPage = BeanUtil.copyProperties(page, Page.class);
        voPage.setRecords(BeanUtil.copyToList(page.getRecords(), SysConfigListVO.class));
        return voPage;
    }

    @Override
    public List<SysConfigListVO> selectList(SysConfigQueryDTO req) {
        LambdaQueryWrapper<SysConfig> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigName()), SysConfig::getConfigName, req.getConfigName());
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigKey()), SysConfig::getConfigKey, req.getConfigKey());
        queryWrapper.orderByDesc(SysConfig::getCreateTime);
        List<SysConfig> list = sysConfigMapper.selectList(queryWrapper);
        return BeanUtil.copyToList(list, SysConfigListVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysConfigAddDTO req) {
        if (!this.checkUniqueConfigName(req.getConfigName(), null)) {
            throw new CustomException("参数名称已存在");
        }
        if (!this.checkUniqueConfigKey(req.getConfigKey(), null)) {
            throw new CustomException("参数键名已存在");
        }
        SysConfig entity = BeanUtil.copyProperties(req, SysConfig.class);
        sysConfigMapper.insert(entity);
    }

    @CacheEvict(value = CacheConstants.CACHE_PREFIX_SYS_CONFIG, key = "#req.configKey")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysConfigEditDTO req) {
        if (!this.checkUniqueConfigName(req.getConfigName(), req.getId())) {
            throw new CustomException("参数名称已存在");
        }
        if (!this.checkUniqueConfigKey(req.getConfigKey(), req.getId())) {
            throw new CustomException("参数键名已存在");
        }
        SysConfig entity = BeanUtil.copyProperties(req, SysConfig.class);
        sysConfigMapper.updateById(entity);
    }

    @CacheEvict(value = CacheConstants.CACHE_PREFIX_SYS_CONFIG, allEntries = true)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(String ids) {
        List<String> idList = Arrays.asList(ids.split(","));
        idList.forEach(item -> {
            sysConfigMapper.deleteById(item);
        });
    }

    @Override
    public SysConfigVO view(String id) {
        SysConfig entity = sysConfigMapper.selectById(id);
        return BeanUtil.copyProperties(entity, SysConfigVO.class);
    }

    @Cacheable(value = CacheConstants.CACHE_PREFIX_SYS_CONFIG, key = "#key", sync = true)
    @Override
    public String getConfigValueByKey(String key) {
        SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
                .eq(SysConfig::getConfigKey, key)
                .eq(SysConfig::getStatus, StatusEnum.YES.getCode()));
        if (Objects.isNull(sysConfig)) {
            return "";
        }
        return sysConfig.getConfigValue();
    }

    @CacheEvict(value = CacheConstants.CACHE_PREFIX_SYS_CONFIG, allEntries = true)
    @Override
    public void clearAllCache() {
        log.info("清除系统参数缓存");
    }

    private Boolean checkUniqueConfigName(String value, Long id) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysConfig entity = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getConfigName, value));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

    private Boolean checkUniqueConfigKey(String value, Long id) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysConfig entity = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getConfigKey, value));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

}
